package juc;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

class MyCache{
    //缓存，内存可见
    private volatile Map<String,Object> cache = new HashMap<>();
    ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

    //写缓存方法
    public void write(String key,Object value){
        rwLock.writeLock().lock();
        try {
            System.out.println("线程："+Thread.currentThread().getName()+" 写入："+key);
            cache.put(key,value);
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程："+Thread.currentThread().getName()+" 写入完成");
        }finally {
            rwLock.writeLock().unlock();
        }

    }

    //读缓存方法
    public void read(String key){
        rwLock.readLock().lock();
        try {
            System.out.println("线程："+Thread.currentThread().getName()+" 读取："+key);
            Object obj = cache.get(key);
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程："+Thread.currentThread().getName()+" 读取完成,值为："+obj);
        }finally {
            rwLock.readLock().unlock();
        }

    }
}

public class MyReadWriteLock {

    public static void main(String[] args) {
        MyCache cache = new MyCache();
        for (int i=0;i<3;i++){//3线程并发写
            final int tem = i;
            new Thread(()->{
                cache.write(tem+"",tem+"");
            },String.valueOf(i)).start();
        }
        for (int i=0;i<3;i++){//3线程并发读
            final int tem = i;
            new Thread(()->{
                cache.read(tem+"");
            },String.valueOf(i)).start();
        }

    }
}
/*
线程：0 写入：0
线程：0 写入完成
线程：1 写入：1
线程：1 写入完成
线程：2 写入：2
线程：2 写入完成

线程：0 读取：0
线程：1 读取：1
线程：2 读取：2
线程：2 读取完成,值为：2
线程：1 读取完成,值为：1
线程：0 读取完成,值为：0

可以看到，写入操作，严格一一对应，而读操作，则是并发进行
 */